일반적인 선형 회귀 모형은 다음과 같은 수식을 만족한다.
$$ y_i = \sum_{i=1}^{D} w_i x_i = w^T x $$이 때 가중치 벡터 $w$의 차원은 독립 변수의 차원과 같다. 즉 $x \in \mathbf{R}^D$ 이면 $w \in \mathbf{R}^D$ 이다.
선형 기저 함수 모형(Linear Basis Function Models)은 x를 직접 선형 조합(linear combination)하지 않고 기저 함수를 통해 변환한 값을 새로운 독립 변수로 가정하고 선형 회귀 모형을 적용한 것과 같다. 따라서 기저 함수에 따라 가중치 벡터의 차원이 달라질 수 있다. 즉, $ \phi(\cdot): \mathbf{R}^D \rightarrow \mathbf{R}^M $ 이면 $w \in \mathbf{R}^M$ 이다.
$$ y_i = \sum_{j=1}^{M} w_j \phi_j(x) = w^T \phi(x) $$언제 쓰느냐? 밑에 1차항으로 할 때에는 잘 안 맞지만 2, 3, 4 차항으로 늘릴수록 잘 맞게 된다.
다항 회귀는 다음과 같은 다항식 함수를 기저 함수로 사용하는 선형 기저 함수 모형의 일종이다.
$$ 1, x, x^2, \ldots, x^M $$따라서 종속 변수와 독립 변수의 관계는 다음과 같이 표현할 수 있다.
$$ y = w_0 + w_1x + w_2x^2 + \ldots + w_M x^M $$statsmodels에서는 OLS
클래스의 from_formula
메서드를 사용하여 다항 회귀를 할 수 있다.
In [2]:
np.random.seed(0)
n_samples = 30
X = np.sort(np.random.rand(n_samples))
y = np.cos(1.5 * np.pi * X) + np.random.randn(n_samples) * 0.1
dfX = pd.DataFrame(X, columns=["x"])
dfX = sm.add_constant(dfX)
dfy = pd.DataFrame(y, columns=["y"])
df = pd.concat([dfX, dfy], axis=1)
print(sm.OLS.from_formula("y ~ x", data=df).fit().summary())
print(sm.OLS.from_formula("y ~ x + I(x**2)", data=df).fit().summary())
print(sm.OLS.from_formula("y ~ x + I(x**2) + I(x**3)", data=df).fit().summary())
print(sm.OLS.from_formula("y ~ x + I(x**2) + I(x**3) + I(x**4)", data=df).fit().summary())
print(sm.OLS.from_formula("y ~ x + I(x**2) + I(x**3) + I(x**4) + I(x**5)", data=df).fit().summary())
Scikit-Learn에서는 preprocessing 서브 패키지의 PolynomialFeatures
클래스를 사용하여 다항 회귀를 할 수 있다.
In [3]:
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.pipeline import Pipeline
In [5]:
def polyreg(degree, seed=0, plot=True):
polynomial_features = PolynomialFeatures(degree=degree)
linear_regression = LinearRegression()
model = Pipeline([("polynomial_features", polynomial_features),
("linear_regression", linear_regression)])
np.random.seed(seed)
n_samples = 30
X = np.sort(np.random.rand(n_samples))
y = np.cos(1.5 * np.pi * X) + np.random.randn(n_samples) * 0.1
X = X[:, np.newaxis]
model.fit(X, y)
if plot:
plt.scatter(X, y)
xx = np.linspace(0, 1, 1000)
plt.plot(xx, model.predict(xx[:, np.newaxis]))
plt.ylim(-2, 2)
plt.show()
reg = model.named_steps["linear_regression"]
return reg.coef_, reg.intercept_
In [6]:
polyreg(1)
Out[6]:
In [7]:
polyreg(2)
Out[7]:
In [8]:
polyreg(3)
Out[8]:
In [9]:
polyreg(4)
Out[9]:
In [10]:
polyreg(5)
Out[10]:
In [13]:
polyreg(50)
Out[13]:
모형을 특정 샘플 데이터에 대해 과도하게 최적화하는 것을 과최적화(overfitting)이라고 한다.
과최적화는
이러한 상황에서는 같은 조건에 대해 답이 복수개 존재할 수 있기 때문이다.
과최적화가 문제가 되는 이유는 다음과 같다.
나쁜 이유? 회귀 결과의 안전성을 해치게 된다.
In [14]:
polyreg(2, 0)
Out[14]:
In [15]:
polyreg(2, 1)
Out[15]:
In [16]:
polyreg(2, 2)
Out[16]:
In [17]:
polyreg(50, 1)
Out[17]:
In [18]:
polyreg(50, 2)
Out[18]:
In [19]:
polyreg(50, 3)
Out[19]: